$:.unshift File.join(File.dirname(__FILE__),'..','lib')

require 'date'
require 'fileutils'
require 'pathname'
require 'test/unit'

require 'helpers'
require 'model'

class TcModel < Test::Unit::TestCase

  TEST_DIR = 'test_data'
  SAMPLE_DIR = 'sample_data'
  
  def setup
    FileUtils.rm_rf(TEST_DIR)
    @model = Model.new(TEST_DIR)
    @account_assets = @model.add_account("Assets", :debit, @model.root_account)
    @account_checking = @model.add_account("Checking", :debit, @account_assets)
    @account_cash = @model.add_account("Cash", :debit, @account_assets)
    @account_equity = @model.add_account("Equity", :credit, @model.root_account)
    @account_open_bal = @model.add_account("Opening Balances", :credit, @account_equity)
    @account_earnings = @model.add_account("Retained Earnings", :credit, @account_equity)
    @account_hh_expense = @model.add_account("Household Expense", :debit, @account_earnings)
    @model.save_accounts
  end
  
  def teardown
  end
  
  def test_account_basic
    #check data file stuff
    assert(File.exists?(TEST_DIR) && File.directory?(TEST_DIR))
    assert(File.exists?("#{TEST_DIR}/accounts.yaml"))
    
    #check accounts
    assert_equal(@account_assets, @model.find_account("Assets")) #test underlying method
    assert_equal(@account_checking, @model["Checking"]) #now use synonyn for find_account
    assert_equal(@account_equity, @model["Equity"])
    assert_equal(@account_open_bal, @model["Opening Balances"])
    assert_equal(@account_earnings, @model["Retained Earnings"])
    assert_equal(@account_hh_expense,@model["Household Expense"])
    
    #check subaccounts
    assert_equal([@account_checking, @account_cash], @model.find_subaccounts(@account_assets))
    assert_equal(
      [@account_open_bal, @account_earnings, @account_hh_expense],
      @model.find_all_subaccounts(@account_equity)
    )
  end

  def test_model_loading
    @model = Model.new(SAMPLE_DIR)
    assert_equal("Assets", @model["Checking"].parent_account.account_name)
    assert_equal("Equity", @model["Retained Earnings"].parent_account.account_name)
    assert_equal("Liabilities", @model["Credit Card"].parent_account.account_name)
    assert_equal("Retained Earnings", @model["Expense"].parent_account.account_name)
  end

  def test_ofx
    ofx = @model.import_ofx("#{SAMPLE_DIR}/ofx_sample/checking.ofx")
    assert_equal('OFXSGML', ofx.header.data)
    assert(File.exists?("#{TEST_DIR}/ofx/00000000.yaml"))
    FileUtils.cp("#{TEST_DIR}/ofx/00000000.yaml", "#{SAMPLE_DIR}/ofx/00000000.yaml")
    ofx = @model.import_ofx("#{SAMPLE_DIR}/ofx_sample/credit_card.ofx")
    assert_equal('OFXSGML', ofx.header.data)
    assert(File.exists?("#{TEST_DIR}/ofx/00000001.yaml"))
    FileUtils.cp("#{TEST_DIR}/ofx/00000001.yaml", "#{SAMPLE_DIR}/ofx/00000001.yaml")
  end
  
  def test_transaction_posting
    tx = Helpers.transaction_simple("2008-07-15", @account_open_bal, @account_checking, BigDecimal.new("23.45"))
    @model.post(tx)
    assert_equal(1, @model.transactions.length)
    tx = Helpers.transaction_simple("2008-07-15", @account_checking, @account_hh_expense, BigDecimal.new("12.34"))
    @model.post(tx)
    assert_equal(2, @model.transactions.length)
    
    checking_tx = @model.find_transactions(@account_checking)
    assert_equal(2, checking_tx.length)
  end
  
  def test_transaction_invalid
    tx = Helpers.invalid_transaction
    assert(!tx.is_balanced?)
    assert_raise(RuntimeError) { @model.post(tx)}
  end
 
  def test_transactions_post_three
    tx = Helpers.transaction_simple("2008-04-01", @account_open_bal, @account_checking, BigDecimal.new("9.99"))
    @model.post(tx)
    assert_equal(1, @model.transactions.length)
    amt = BigDecimal.new("1.11")
    [ "2008-07-15", "2008-07-04", "2008-06-09"].each do |dt|
      tx = Helpers.transaction_simple(dt, @account_checking, @account_hh_expense, amt)
      @model.post(tx)
      amt += BigDecimal.new("1.11")
    end
    assert_equal(4, @model.transactions.length)
    tx = @model.transactions[0] #should get opening balance tx
    assert_equal(Date.parse("2008-04-01"), tx.date)
    assert_equal(BigDecimal.new("9.99"), tx.total_credits)
    assert_equal(BigDecimal.new("9.99"), tx.total_debits)
  end
  
  def test_transactions_modify_delete
    tx = Helpers.transaction_simple("2008-08-16", @account_open_bal, @account_checking, BigDecimal.new("44.44"))
    @model.post(tx)
    assert_equal(BigDecimal.new("44.44"), @account_checking.current_balance)
    tx = Helpers.transaction_simple("2008-08-16", @account_open_bal, @account_cash, BigDecimal.new("11.11"))
    @model.post(tx)
    assert_equal(BigDecimal.new("11.11"), @account_cash.current_balance)

    tx = Transaction.new("2008-08-16")
    tx.add_credit(@account_checking, BigDecimal.new("33.33"))
    tx.add_credit(@account_cash, BigDecimal.new("11.11"))
    tx.add_debit(@account_hh_expense, BigDecimal.new("44.44"))
    @model.post(tx)
    assert_equal(BigDecimal.new("11.11"), @account_checking.current_balance)
    assert_equal(BigDecimal.new("0.0"), @account_cash.current_balance)
    assert_equal(BigDecimal.new("11.11"), @account_assets.current_balance)
    assert_equal(BigDecimal.new("44.44"), @account_hh_expense.current_balance)

    tx.remove_entry(1)
    tx.adjust_entry(0, BigDecimal.new("44.44"))
    assert_equal(BigDecimal.new("0.0"), @account_checking.current_balance)
    assert_equal(BigDecimal.new("11.11"), @account_cash.current_balance)
    assert_equal(BigDecimal.new("11.11"), @account_assets.current_balance)
  end
  
end
